package com.liik.game.mvc.tiled;

import android.graphics.Canvas;
import android.graphics.Color;

import com.liik.game.mvc.GameModel;
import com.liik.game.mvc.GameRenderer;
import com.liik.game.mvc.object.Display;
import com.liik.game.mvc.object.Menu;
import com.liik.game.mvc.object.Navigation;
import com.liik.game.mvc.object.Menu.Item;
import com.liik.game.mvc.tiled.object.Entity;
import com.liik.game.mvc.tiled.object.Tile;
import com.liik.game.util.Vector;

public abstract class TiledGameRenderer implements GameRenderer {

	private Vector offsetHelper = new Vector();

	@Override
	public final void render(GameModel model, Navigation navigation, Display display, Canvas canvas) {
		TiledGameModel gameModel = (TiledGameModel) model;
		Menu menu = gameModel.getMenu();

		// clear screen first
		canvas.drawColor(Color.BLACK);

		// draw tiles
		int minX = (int) Math.floor(display.offset.x);
		int maxX = (int) Math.floor(display.offset.x + display.dimensions.x + 1);
		int minY = (int) Math.floor(display.offset.y);
		int maxY = (int) Math.floor(display.offset.y + display.dimensions.y + 1);
		offsetHelper.set(display.offset);
		offsetHelper.mul(display.tileToPixel);
		for (int x = minX; x < maxX; ++x) {
			for (int y = minY; y < maxY; ++y) {
				Tile tile = gameModel.getTile(x, y);
				renderTile(tile, canvas, (x * display.tileToPixel) - offsetHelper.x, (y * display.tileToPixel) - offsetHelper.y, display.tileToPixel, display.tileToPixel);
			}
		}

		// draw target
		if (navigation.pressed) {
			renderNavigationTarget(canvas, navigation.screenTarget.x, navigation.screenTarget.y);
		}

		// draw all other entities
		Entity[] entities = gameModel.getAllEntities();
		for (int i = 0; i < entities.length; ++i) {
			Entity entity = entities[i];
			if (entity != null && entity.isActive()) {
				calculateScreenPosition(entity, display, offsetHelper);
				if (offsetHelper.x + display.tileToPixel >= 0 && offsetHelper.x < display.screensize.x && offsetHelper.y + display.tileToPixel >= 0
						&& offsetHelper.y < display.screensize.y) {
					renderEntity(entity, canvas, offsetHelper.x, offsetHelper.y, display.tileToPixel, display.tileToPixel);
				}
			}
		}

		// draw hero
		Entity hero = gameModel.getHero();
		calculateScreenPosition(hero, display, offsetHelper);
		renderEntity(hero, canvas, offsetHelper.x, offsetHelper.y, display.tileToPixel, display.tileToPixel);

		// draw menu
		for (int i = 0; i < menu.getNumberOfItems(); ++i) {
			Item item = menu.getItem(i);
			if (item != null && item.visible) {
				renderMenuItem(item, canvas);
			}
		}
	}

	private void calculateScreenPosition(Vector tilePos, Display display, Vector out) {
		out.set(tilePos);
		out.sub(display.offset);
		out.x -= 0.5f;
		out.y -= 0.5f;
		out.mul(display.tileToPixel);
	}

	protected abstract void renderMenuItem(Item item, Canvas canvas);

	protected abstract void renderEntity(Entity entity, Canvas canvas, float x, float y, float width, float height);

	protected abstract void renderNavigationTarget(Canvas canvas, float x, float y);

	protected abstract void renderTile(Tile tile, Canvas canvas, float x, float y, float width, float height);
}
